package 面试.美团;

import java.util.*;

/**
 * @author : K k
 * @date : 10:33 2020/9/13
 */
public class 美团3 {
    static int count=0; //记录答案数
    static List<Integer> list=new ArrayList<>();

    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        //输入包括三个数 n代表总数  k代表每个数大于1小于k （1≤d≤k≤n≤1000）
        int n= in.nextInt();
        int k= in.nextInt();
        int d= in.nextInt();

        //回溯算法
        System.out.println(findTotal(n, k, d));
    }

    private static int findTotal(int target, int k, int d) {
        //k和d可以代表限制和初始索引
        dfsSovler(target,k,d);

        return count%998244353;
    }

    private static void dfsSovler(int target, int k, int d) {
        //终止条件
        if (target<0){
            return;
        }
        if (target==0 ){
            //Collections.sort(list);
            Integer[] res = (Integer[]) list.toArray(new Integer[list.size()]);
            quick(res);
            if (res[list.size()-1]<d){
                return;
            }
            count=(count+1)%998244353;
            return;
        }

        for (int i=1;i<=k;i++){
            //进行dfs
            list.add(i);
            dfsSovler(target-i,k,d);
            list.remove(list.size()-1);
        }
    }

   /* static int max(List<Integer> list){
        int max=0;
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()){
            int x=iterator.next();
            if (max<x){
                max=x;
            }
        }
        return max;
    }*/

    //快排
    private static void quick(Integer[] a) {
        if(a.length>0){
            quickSort(a,0,a.length-1);
        }
    }
    //选择一个基准划分
    private static void quickSort(Integer[] a, int low, int high) {
        if(low<high) { //如果不加这个判断递归会无法退出导致堆栈溢出异常
            int middle = getMiddle(a, low, high);
            //递归将剩下的分组进行再快排,知道参数low=high
            quickSort(a, low, middle - 1);
            quickSort(a, middle + 1, high);
        }
    }

    private static int getMiddle(Integer[] a, int low, int high) {
        int temp=a[low]; //以第一个值为基准
        while (low<high){
            while (low<high&&a[high]>=temp){//找到小于基准的值
                high--;
            }
            //存在两种情况，一种是找到了且low<high，则将high赋值到low的位置，第二种是没找到，说明这是升序的不用排序。
            //这样赋值则原来的high处数据可以随时被替换
            a[low]=a[high];
            while (low<high&&a[low]<temp){
                low++;
            }
            a[high]=a[low];
        }
        a[low]=temp; //此时的low和high相等
        return low; //目的是以a[low]为界限分割两个区域（大小）
    }
}
